package top.dancun.eascrawler.http;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.io.IOUtils;
import org.jsoup.nodes.Element;
import org.seimicrawler.xpath.JXDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import top.dancun.eascrawler.entity.PapersPublishedEntity;
import top.dancun.eascrawler.service.PapersPublishedService;
import top.dancun.eascrawler.utils.CNKIFormUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;

/**
 * @author dancun
 */
@Component
@Slf4j
public class CNKIHttp {
    @Autowired
    private PapersPublishedService publishedService;

    @Value("classpath:static/formData.json")
    private Resource resource;
    public JSONObject getFormJson(){
        try {
            String areaData =  IOUtils.toString(resource.getInputStream(), StandardCharsets.UTF_8);
            return (JSONObject) JSON.parse(areaData);
        } catch (IOException e) {
            log.error("",e);
        }
        return null;
    }

    /**
     *
     * @param map 查询条件
     * @return 高校论文发表数量
     * @throws IOException
     */
    //搜索结果插入数据库 搜索前查询数据库 知网容易封ip
    public Long requestCount(Map<String,String> map) throws IOException {

        PapersPublishedEntity papersPublished ;
        LambdaQueryWrapper<PapersPublishedEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(PapersPublishedEntity::getSchoolname,map.get("from"))
                        .eq(PapersPublishedEntity::getYear,map.get("time"));
        papersPublished = publishedService.getOne(wrapper);
//        if (Objects.nonNull(papersPublished)){
//            return papersPublished.getNum();
//        }

        //获取本地json摆荡
        JSONObject originalForm = getFormJson();
        //格式化表单
        JSONObject formatForm = CNKIFormUtils.formFormat(originalForm,map);
        Map<String,String> formMap = JSONObject.parseObject(String.valueOf(formatForm),Map.class);
        //格式化表单(中文)
        JSONObject formatFormCh = CNKIFormUtils.formFormatCh(originalForm,map);
        Map<String,String> chformMap = JSONObject.parseObject(String.valueOf(formatFormCh),Map.class);

        //请求类型，没用到
        MediaType mediaType = MediaType.parse("text/plain");


        Long enNum=0l;
        Long chNum=0l;
        //未发表论文为0
        try{
            enNum =postUtil(formMap);
        }catch (Exception e){
            e.printStackTrace();
        }

        try{
            chNum =postUtil(chformMap);
        }catch (Exception e){
            e.printStackTrace();
        }
        if (Objects.nonNull(papersPublished)){
            papersPublished.setNum(enNum+chNum);
            papersPublished.setChNum(chNum);
            papersPublished.setEnNum(enNum);
            publishedService.updateById(papersPublished);
            return papersPublished.getNum();
        }else{
            papersPublished = new PapersPublishedEntity();
            papersPublished.setYear(map.get("time"));
            papersPublished.setNum(enNum+chNum);
            papersPublished.setChNum(chNum);
            papersPublished.setEnNum(enNum);
            papersPublished.setSchoolname(map.get("from"));
            publishedService.save(papersPublished);
        }

        return chNum+enNum;


    }
    private Long postUtil( Map<String,String> formMap) throws IOException {
        //okhttp请求客户端
        OkHttpClient client = new OkHttpClient().newBuilder()
                .build();
        //form请求提
        MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
        formMap.forEach(builder::addFormDataPart);
        RequestBody body  = builder.build();
        //请求头设置
        Request request = new Request.Builder()
                .url("https://kns.cnki.net/KNS8/Brief/GetGridTableHtml")
                .method("POST", body)
                .addHeader("Origin", "https://kns.cnki.net")
                .addHeader("Referer", "https://kns.cnki.net/kns8/AdvSearch")
                .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.41")
                .addHeader("X-Requested-With", "XMLHttpRequest")
                .addHeader("Cookie", "cangjieStatus_NZKPT2=true; cangjieConfig_NZKPT2=%7B%22status%22%3Atrue%2C%22startTime%22%3A%222022-10-20%22%2C%22endTime%22%3A%222023-10-20%22%2C%22orginHosts%22%3A%22kns.cnki.net%22%2C%22type%22%3A%22mix%22%2C%22poolSize%22%3A%2210%22%2C%22intervalTime%22%3A10000%2C%22persist%22%3Afalse%7D; Ecp_ClientId=d230216154401213351; Ecp_IpLoginFail=230216116.162.57.146; knsLeftGroupSelectItem=1%3B2%3B; Ecp_ClientIp=116.162.57.98; _pk_ref=%5B%22%22%2C%22%22%2C1676612694%2C%22https%3A%2F%2Fwww.bing.com%2F%22%5D; _pk_id=1e514006-9f65-469f-8188-be1786d4ba79.1676533471.2.1676612694.1676612694.; _pk_ses=*; ASP.NET_SessionId=3bx5m4xdfaf0fhioucysdyc0; SID_kns8=015123155; dblang=ch; CurrSortField=%e7%9b%b8%e5%85%b3%e5%ba%a6%2frelevant%2c(%e5%8f%91%e8%a1%a8%e6%97%b6%e9%97%b4%2c%27time%27)+desc; CurrSortFieldType=desc; SID_kns_new=kns25128007")
                .addHeader("Sec-Fetch-Dest", "empty")
                .addHeader("Sec-Fetch-Mode", "cors")
                .addHeader("Sec-Fetch-Site", "same-origin")
                .build();
        Response response = client.newCall(request).execute();
//        System.out.println(response.body().string());
        assert response.body() != null;
        String res = response.body().string();
        //jsoup xpath获取数据
        JXDocument jdoc = JXDocument.create(res);
        Element element = (Element) jdoc.selOne("//div[@id='countPageDiv']/span/em");
        String countstr = element.text().replace(",","");
        Long count = Long.parseLong(countstr);
        response.close();
        return count;
    }
}
